package com.benshou.bsoa.utils;

import com.benshou.bsoa.dto.yida.req.DingTalkMsgReq;
import com.benshou.bsoa.service.yida.RobotService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.function.Supplier;
import java.util.stream.Collectors;


/*
 *  通用重试执行器
 */
@Slf4j
@Service
public class RetryExecutor {

    /**
     * 通用重试执行器
     *
     * @param task         要执行的任务逻辑（无返回值）
     * @param maxRetries   最大重试次数
     * @param waitMillis   每次失败后的等待时间（毫秒）
     * @param taskName     任务名称（用于日志）
     */
    @Resource
    private RobotService robotService; // 注入机器人服务

    public void runWithRetry(Runnable task, int maxRetries, long waitMillis, String taskName) throws Exception {
        int retryCount = 0;
        boolean success = false;
        LocalDateTime startTime = LocalDateTime.now();

        while (!success && retryCount < maxRetries) {
            try {
                retryCount++;
                task.run();
                success = true;

                LocalDateTime endTime = LocalDateTime.now();
                long seconds = Duration.between(startTime, endTime).toSeconds();
                //发送钉钉消息通知
                DingTalkMsgReq msgReq = new DingTalkMsgReq();
                String content = String.format(
                        "✅ 任务执行成功通知\n" +
                                "任务名称：`%s`\n" +
                                "状态：🟢 成功\n" +
                                "执行时间：%s\n\n" +
                                "执行概况：\n" +
                                "> ⏱️ 耗时：`%s 秒`\n" +
                                "> 💾 导入成功率：`100%%`\n",
                        taskName,
                        LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
                        seconds
                );
                msgReq.setContent(content);
                msgReq.setUserIds(Collections.singletonList("1731909932595797"));
                robotService.sendDingRobotMessage(msgReq);
                log.info("✅ [{}] 执行成功（重试次数：{}，总耗时：{} 秒）", taskName, retryCount, seconds);

            } catch (Exception e) {
                LocalDateTime errorTime = LocalDateTime.now();
                long seconds = Duration.between(startTime, errorTime).toSeconds();

                log.warn("❌ [{}] 第 {} 次执行失败（已耗时：{} 秒）：{}", taskName, retryCount, seconds, e.getMessage());

                if (retryCount >= maxRetries) {
                    DingTalkMsgReq msgReq = new DingTalkMsgReq();
                    String content = String.format(
                            "❌ 任务执行失败通知\n" +
                                    "任务名称：%s\n" +
                                    "状态**：🔴 失败\n" +
                                    "错误信息**：%s\n" +
                                    "执行时间**：%s\n\n" +
                                    "---\n" +
                                    "执行概况**：\n" +
                                    "📊 已处理记录：0 条\n" +
                                    "⏱️ 耗时：%d 秒\n",
                            taskName,
                            e.getMessage(),
                            java.time.LocalDateTime.now().toString(),
                            seconds
                    );
                    msgReq.setContent(content);
                    msgReq.setUserIds(Collections.singletonList("1731909932595797"));
                    robotService.sendDingRobotMessage(msgReq);
                    log.error("🚨 [{}] 达到最大重试次数（{}），任务执行终止！", taskName, maxRetries);
                    break;
                }

                try {
                    Thread.sleep(waitMillis);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    log.error("🔌 [{}] 任务等待期间被中断，重试中止！", taskName);
                    break;
                }
            }
        }
    }

    /**
     * 重试执行并返回结果（带返回值的任务）
     */
    public static <T> T callWithRetry(Supplier<T> task, int maxRetries, long waitMillis, String taskName) {
        int retryCount = 0;
        boolean success = false;
        LocalDateTime startTime = LocalDateTime.now();
        T result = null;

        while (!success && retryCount < maxRetries) {
            try {
                retryCount++;
                result = task.get();
                success = true;

                LocalDateTime endTime = LocalDateTime.now();
                long seconds = Duration.between(startTime, endTime).toSeconds();
                log.info("✅ [{}] 执行成功（重试次数：{}，总耗时：{} 秒）", taskName, retryCount, seconds);

            } catch (Exception e) {
                LocalDateTime errorTime = LocalDateTime.now();
                long seconds = Duration.between(startTime, errorTime).toSeconds();

                log.warn("❌ [{}] 第 {} 次执行失败（已耗时：{} 秒）：{}", taskName, retryCount, seconds, e.getMessage());

                if (retryCount >= maxRetries) {
                    log.error("🚨 [{}] 达到最大重试次数（{}），任务执行终止！", taskName, maxRetries);
                    break;
                }

                try {
                    Thread.sleep(waitMillis);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    log.error("🔌 [{}] 任务等待期间被中断，重试中止！", taskName);
                    break;
                }
            }
        }

        return result;
    }
}
